#!/bin/bash

# reverse_tunnel.sh - Script to establish and maintain a reverse SSH tunnel

# --- Configuration - Read from config file ---
CONFIG_FILE="./config.sh"

if [ ! -f "${CONFIG_FILE}" ]; then
    echo "Error: Configuration file '${CONFIG_FILE}' not found."
    echo "Please create it from 'config.template' and fill in your details."
    exit 1
fi

source "${CONFIG_FILE}"

# --- Dependency Checks ---
echo "Checking dependencies..."

# Check for ssh
if ! command -v ssh &> /dev/null; then
    echo "Error: 'ssh' command not found. Please install OpenSSH client."
    exit 1
fi
echo "[OK] ssh client found."

# Check for autossh
if ! command -v autossh &> /dev/null; then
    echo "Error: 'autossh' command not found."
    echo "Please install autossh. On Debian/Ubuntu: sudo apt update && sudo apt install autossh"
    echo "On CentOS/RHEL: sudo yum install autossh (may require EPEL repository)"
    echo "On macOS (via Homebrew): brew install autossh"
    exit 1
fi
echo "[OK] autossh found."

# --- Validate Configuration ---
if [ -z "${REMOTE_USER}" ] || [ -z "${REMOTE_HOST}" ] || [ -z "${REMOTE_PORT_FORWARD}" ] || [ -z "${LOCAL_PORT_TO_FORWARD}" ]; then
    echo "Error: One or more required variables are not set in '${CONFIG_FILE}'"
    echo "Please check REMOTE_USER, REMOTE_HOST, REMOTE_PORT_FORWARD, LOCAL_PORT_TO_FORWARD."
    exit 1
fi

# --- SSH Key Check (Informational) ---
echo "INFO: This script relies on SSH key-based authentication."
echo "Ensure you have generated an SSH key pair on this machine (ssh-keygen)"
echo "and copied the public key to the '${REMOTE_USER}@${REMOTE_HOST}' server's ~/.ssh/authorized_keys file."
echo "Example: ssh-copy-id ${REMOTE_USER}@${REMOTE_HOST}"

# --- Autossh Parameters ---
# -M 0: Disables the monitoring port for autossh itself, relying on SSH's keep-alive.
# If you prefer a monitoring port, set AUTOSSH_MONITOR_PORT in config.sh (e.g., 20000)
# and change -M 0 to -M "${AUTOSSH_MONITOR_PORT}"
# -N: Do not execute a remote command. This is useful for just forwarding ports.
# -f: Requests ssh to go to background just before command execution.
# -o "ServerAliveInterval 60": Send a keep-alive message every 60 seconds.
# -o "ServerAliveCountMax 3": Disconnect if 3 keep-alive messages are missed.
# -o "ExitOnForwardFailure yes": Exit if the port forwarding fails.
# -o "StrictHostKeyChecking no": Automatically add new host keys to the user known hosts files (consider security implications).
# -o "UserKnownHostsFile=/dev/null": Avoids issues with changing host keys if the server IP changes (consider security implications).
# For higher security, remove StrictHostKeyChecking=no and UserKnownHostsFile=/dev/null after the first successful connection.
# -R ${REMOTE_PORT_FORWARD}:localhost:${LOCAL_PORT_TO_FORWARD}: Remote port forwarding.

AUTOSSH_OPTIONS="-M ${AUTOSSH_MONITOR_PORT:-0}"
AUTOSSH_OPTIONS+=" -N -f"
AUTOSSH_OPTIONS+=" -o ServerAliveInterval=${AUTOSSH_SERVER_ALIVE_INTERVAL:-60}"
AUTOSSH_OPTIONS+=" -o ServerAliveCountMax=${AUTOSSH_SERVER_ALIVE_COUNT_MAX:-3}"
AUTOSSH_OPTIONS+=" -o ExitOnForwardFailure=yes"
AUTOSSH_OPTIONS+=" -o StrictHostKeyChecking=${AUTOSSH_STRICT_HOST_KEY_CHECKING:-no}" # For initial setup, can be changed to 'yes' later
AUTOSSH_OPTIONS+=" -o UserKnownHostsFile=${AUTOSSH_USER_KNOWN_HOSTS_FILE:-/dev/null}" # For initial setup

if [ -n "${SSH_IDENTITY_FILE}" ]; then
    if [ ! -f "${SSH_IDENTITY_FILE}" ]; then
        echo "Error: Specified SSH_IDENTITY_FILE '${SSH_IDENTITY_FILE}' not found."
        exit 1
    fi
    AUTOSSH_OPTIONS+=" -i ${SSH_IDENTITY_FILE}"
    echo "INFO: Using SSH identity file: ${SSH_IDENTITY_FILE}"
fi

TUNNEL_CMD="autossh ${AUTOSSH_OPTIONS} -R ${REMOTE_PORT_FORWARD}:localhost:${LOCAL_PORT_TO_FORWARD} ${REMOTE_USER}@${REMOTE_HOST}"

if [ -n "${REMOTE_SSH_PORT}" ] && [ "${REMOTE_SSH_PORT}" != "22" ]; then
    TUNNEL_CMD+=" -p ${REMOTE_SSH_PORT}"
fi

# --- Start Tunnel ---
echo "Attempting to start the reverse SSH tunnel..."
echo "Command: ${TUNNEL_CMD}"

# Set AUTOSSH_PIDFILE to manage the autossh process
export AUTOSSH_PIDFILE="/tmp/autossh_reverse_tunnel_${REMOTE_PORT_FORWARD}.pid"

# Check if a tunnel is already running for this specific remote port
if [ -f "${AUTOSSH_PIDFILE}" ]; then
    if ps -p "$(cat "${AUTOSSH_PIDFILE}")" > /dev/null; then
        echo "An autossh process with PID $(cat "${AUTOSSH_PIDFILE}") seems to be already running for this configuration."
        echo "If you want to restart, please stop it first (e.g., using 'kill $(cat "${AUTOSSH_PIDFILE}")' or the stop script)."
        exit 0
    else
        echo "Found stale PID file '${AUTOSSH_PIDFILE}'. Removing it."
        rm -f "${AUTOSSH_PIDFILE}"
    fi
fi

${TUNNEL_CMD}

# Give autossh a moment to establish the connection and background itself
sleep 5

if [ -f "${AUTOSSH_PIDFILE}" ] && ps -p "$(cat "${AUTOSSH_PIDFILE}")" > /dev/null; then
    echo "Reverse SSH tunnel started successfully."
    echo "Public access (from your external server): ssh -p ${REMOTE_PORT_FORWARD} <your_local_machine_user>@localhost"
    echo "Or, if you forwarded a web server: http://localhost:${REMOTE_PORT_FORWARD} (on the external server)"
    echo "The autossh process PID is $(cat "${AUTOSSH_PIDFILE}"). Stored in ${AUTOSSH_PIDFILE}"
else
    echo "Error: Failed to start the reverse SSH tunnel or autossh did not daemonize correctly."
    echo "Check autossh logs if configured (e.g., AUTOSSH_LOGFILE) or run the command manually without -f for debugging:"
    echo "autossh -M ${AUTOSSH_MONITOR_PORT:-0} -N -o ServerAliveInterval=${AUTOSSH_SERVER_ALIVE_INTERVAL:-60} -o ServerAliveCountMax=${AUTOSSH_SERVER_ALIVE_COUNT_MAX:-3} -o ExitOnForwardFailure=yes -R ${REMOTE_PORT_FORWARD}:localhost:${LOCAL_PORT_TO_FORWARD} ${REMOTE_USER}@${REMOTE_HOST} ${SSH_IDENTITY_FILE:+-i "$SSH_IDENTITY_FILE"} ${REMOTE_SSH_PORT:+-p "$REMOTE_SSH_PORT"}"
    exit 1
fi

exit 0

